package com.zzyl.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONUtil;
import com.aliyun.iot20180120.Client;
import com.aliyun.iot20180120.models.*;
import com.zzyl.constant.CacheConstant;
import com.zzyl.dto.DeviceDto;
import com.zzyl.entity.Device;
import com.zzyl.enums.BasicEnum;
import com.zzyl.enums.DeviceLocationTypeEnum;
import com.zzyl.enums.DevicePhysicalLocationTypeEnum;
import com.zzyl.exception.BaseException;
import com.zzyl.mapper.DeviceMapper;
import com.zzyl.properties.AliIoTConfigProperties;
import com.zzyl.service.DeviceService;
import com.zzyl.utils.ObjectUtil;
import com.zzyl.vo.ProductVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class DeviceServiceImpl implements DeviceService {
    @Autowired
    private DeviceMapper deviceMapper;
    @Autowired
    private Client client;
    @Autowired
    private AliIoTConfigProperties aliIoTConfigProperties;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    /**
     * 从物联网平台同步产品列表
     */
    @Override
    public void syncProductList() throws Exception {
        QueryProductListRequest request = new QueryProductListRequest();
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        request.setPageSize(200);
        request.setCurrentPage(1);

        QueryProductListResponse response = client.queryProductList(request);

        if (!response.getBody().success) {
            throw new BaseException(BasicEnum.IOT_REGISTER_DEVICE_ERROR);
        }
        //获取到从iot平台同步的产品列表
        List<QueryProductListResponseBody.QueryProductListResponseBodyDataListProductInfo> productInfo =
                response.getBody().getData().getList().getProductInfo();

        List<ProductVo> voList = productInfo.stream().map(p -> {
            ProductVo vo = BeanUtil.toBean(p, ProductVo.class);
            return vo;
        }).collect(Collectors.toList());
        //将产品列表存入redis
        redisTemplate.opsForValue().set(CacheConstant.ALL_PRODUCT_KEY, JSONUtil.toJsonStr(voList));
    }

    /**
     * 查询所有产品列表
     *
     * @return
     */
    @Override
    public List<ProductVo> allProduct() {
        //从redis中获取产品列表
        String json = redisTemplate.opsForValue().get(CacheConstant.ALL_PRODUCT_KEY);
        //2.判断json是否为空 如果为空则返回一个空的集合
        if (ObjectUtil.isEmpty(json)) {
            return Collections.emptyList();
        }

        //3.转换数据并返回
        List<ProductVo> productVoList = JSONUtil.toList(json, ProductVo.class);
        return productVoList;
    }

    /**
     * 注册设备
     */
    @Override
    public void registerDevice(DeviceDto deviceDto) {
        //1. 校验设备的名字是否使用过了 如果使用了 则抛出异常
        Integer count = deviceMapper.countName(deviceDto.getDeviceName());
        if (count > 0) {
            throw new BaseException(BasicEnum.DEVICE_NAME_EXIST);
        }
        //2. 新增设备到iot平台
        RegisterDeviceRequest request = deviceDto.getRegisterDeviceRequest();
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        RegisterDeviceResponse response = null;
        try {
            response = client.registerDevice(request);
        } catch (Exception e) {
            //3. 校验新增是否成功 如果失败 则抛出异常 - 主要针对的是网络异常 超时等异常情况
            throw new BaseException(BasicEnum.IOT_REGISTER_DEVICE_ERROR);
        }
        if (!response.getBody().success || response == null) {
            throw new BaseException(BasicEnum.IOT_REGISTER_DEVICE_ERROR);
        }

        //4. 判断设备的安装位置是否是老人 如果是 则需要把physical_location_type 设置为-1
        if (deviceDto.getLocationType().equals(DeviceLocationTypeEnum.PORTABLE_DEVICE.getOrdinal())) {
            deviceDto.setPhysicalLocationType(DevicePhysicalLocationTypeEnum.ELDER.getOrdinal());
        }
        //5. 到iot平台查询设备的详细信息
        QueryProductRequest req = new QueryProductRequest();
        req.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        req.setProductKey(deviceDto.getProductKey());
        try {
            QueryProductResponse queryProductResponse = client.queryProduct(req);
            if (null != queryProductResponse && queryProductResponse.getBody().success) {
                String productName = queryProductResponse.getBody().getData().getProductName();
                //6. 分装pojo(deviceDto,设备的详细信息)
                Device device = BeanUtil.toBean(deviceDto, Device.class);
                device.setProductName(productName);
                device.setIotId(response.getBody().getData().getIotId());
                device.setHaveEntranceGuard(0);
                //7. 调用mapper 插入设备数据
                deviceMapper.insert(device);
            } else {
                throw new RuntimeException();
            }
        } catch (Exception e) {
            //8. 如果新增失败 则删除iot平台新增的设备
            DeleteDeviceRequest deleteReq = new DeleteDeviceRequest();
            deleteReq.setDeviceName(deviceDto.getDeviceName());
            deleteReq.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
            deleteReq.setProductKey(deviceDto.getProductKey());
            deleteReq.setIotId(response.getBody().getData().getIotId());
            try {
                DeleteDeviceResponse deviceResponse = client.deleteDevice(deleteReq);
            } catch (Exception ex) {
                //9. 如果删除失败 那么需要通过人工的方式进行手动删除设备
                throw new BaseException(BasicEnum.IOT_DELETE_DEVICE_ERROR);
            }
        }
    }
}
